package cn.dogger.easyboot.redis.jedis;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.params.SetParams;

import java.util.Collections;
import java.util.Objects;
import java.util.UUID;

/**
 * jedis工具类
 * @author dogger
 * 2022/5/15 13:31
 */
@Component
@Lazy
public class JedisUtils {

    private final Jedis jedis;

    @Value("spring.redis.host")
    private String redisHost;

    @Value("spring.redis.password")
    private String redisPassword;

    @Value("spring.redis.port")
    private int redisPort;

    /**
     * 锁id
     */
    private final String lockId;


    /**
     * 锁超时时间
     */
    public final static Long GET_LOCK_WAIT_TIME_OUT =300000L;

    /**
     * 设置锁成功返回
     */
    private final static String SET_LOCK_SUCCESS ="OK";

    /**
     * 删除锁的lua脚本
     */
    private final static String DELETE_LOCK = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

    /**
     * 可重入式锁的用户线程
     */
    private static ThreadLocal<String> THREAD_LOCAL;
    public JedisUtils(){
        try (JedisPool jedisPool = new JedisPool(redisHost, redisPort)) {
            this.jedis = jedisPool.getResource();
        }
       // this.jedis.auth(redisPassword);
        this.lockId = UUID.randomUUID().toString();
    }


    /**
     * 设置锁
     * @param key 锁key
     * @param setParams 只能取SetParams.nx()或者SetParams.xx()，如果取NX，则只有当key不存在是才进行set，如果取XX，则只有当key已经存在时才进行set;
     * 只能取.ex()或者.px()，代表数据过期时间的单位，EX代表秒，PX代表毫秒。
     * @return 返回锁id
     */
    public String setLock(String key,SetParams setParams){
       return SET_LOCK_SUCCESS.equals(jedis.set(key, lockId,setParams))?lockId:null;
    }

    /**
     * 设置锁
     * @param key 锁key
     * @param setParams 只能取SetParams.nx()或者SetParams.xx()，如果取NX，则只有当key不存在是才进行set，如果取XX，则只有当key已经存在时才进行set;
     * 只能取.ex()或者.px()，代表数据过期时间的单位，EX代表秒，PX代表毫秒。
     * @param lockId 锁id
     * @return 返回锁id
     */
    public String setLock(String key,SetParams setParams,String lockId){
        return SET_LOCK_SUCCESS.equals(jedis.set(key, lockId,setParams))?lockId:null;
    }

    /**
     * 删除锁
     * @param key 锁key
     * @param lockId 锁Id
     */
    public boolean  deleteLock(String key,String lockId){
        return 1 == Integer.parseInt(String.valueOf(this.jedis.eval(DELETE_LOCK, Collections.singletonList(key), Collections.singletonList(lockId))));
    }

}
